package cn.edu.zut.hhr.utils;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class RedisService{

    public void expire(String key, long time){
        /**
         * 防止缓存雪崩
         */
        int random = (int)(Math.random()*1000);
        redisTemplate.expire(key,time+random,TimeUnit.SECONDS);
    }

    /**
     * 这里是没问题的,虽然我们注册的Bean对象是<Stirng,Object>的
     * 但Object可以接收任意类型,也就是说这个T只是在当前的RedisUtil中进行限定val必须序列化
     * 换言之这还有些危险,因为其他程序员可以直接获取到RedisTemplate对象然后让他缓存未序列化的对象
     * 不过Redis帮我们解决了,lettuce规定只有序列化的对象能被缓存,否则报错.
     */

    @Resource(name = "redisTemplate")
    private RedisTemplate<String,Object> redisTemplate;

    public void del(String key){
        redisTemplate.delete(key);
    }

    public void set(String key, Object val){
        redisTemplate.opsForValue().set(key,val);
    }

//    public void setex(String key, Object val, long time, TimeUnit timeUnit){
//        redisTemplate.opsForValue().set(key,val,time,timeUnit);
//    }

    public void setex(String key, Object val, long time){
        /**
         * 防止缓存雪崩
         */
        int random = (int)(Math.random()*1000);
        redisTemplate.opsForValue().set(key,val,time + random,TimeUnit.SECONDS);
    }

//    public Boolean setnxex(String key, Object val, long time, TimeUnit timeUnit){
//        return redisTemplate.opsForValue().setIfAbsent(key,val,time,timeUnit);
//    }

    public Boolean setnxex(String key, Object val, long time){
        int random = (int)(Math.random()*1000);
        return redisTemplate.opsForValue().setIfAbsent(key,val,time + random,TimeUnit.SECONDS);
    }

    public Object get(String key){
        return redisTemplate.opsForValue().get(key);
    }

    public Object getSet(String key, Object val){
        return redisTemplate.opsForValue().getAndSet(key,val);
    }

    public void incr(String key){
        redisTemplate.opsForValue().increment(key);
    }

    public void incr(String key, long count){
        redisTemplate.opsForValue().increment(key,count);
    }

    public void decr(String key){
        redisTemplate.opsForValue().decrement(key);
    }

    public void decr(String key, long count){
        redisTemplate.opsForValue().decrement(key,count);
    }
    /**
     * 对set的操作
     */
    public void sAddex(String key, Object val){
        redisTemplate.opsForSet().add(key,val);
    }

    public Set zGet(String key){
        return redisTemplate.opsForSet().members(key);
    }

    public void zAdd(String key, Object ...val){
        redisTemplate.opsForSet().add(key,val);
    }

    public Long zSize(String key){
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * hyperloglog
     */
    public Long pfSize(String key){
        return redisTemplate.opsForHyperLogLog().size(key);
    }

    public Long pfAdd(String key, Object ...val){
        return redisTemplate.opsForHyperLogLog().add(key,val);
    }

    public Long pfUnion(String key, String ...keys){
        return redisTemplate.opsForHyperLogLog().union(key,keys);
    }

}
